home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 8
/
Aminet 8 (1995)(GTI - Schatztruhe)[!][Oct 1995].iso
/
Aminet
/
dev
/
debug
/
Disectv18b.lha
/
document
/
DisectV1.8.doc
next >
Wrap
Text File
|
1995-07-12
|
125KB
|
2,597 lines
* ------------------------------------------------------------------------- *
Disect V1.8 - © DMA 1994-5 26.11.94 ->
========================== ===========
1) Introduction * READ THIS FIRST !!!
2) Disect Request Windows * life will be easier if you read this!
3) The Program Screen
4) A Disassembler Tutorial * DO THIS to realise the potential!
5) Symbol Selection Window * life will be easier if you read this!
6) Address Functions
7) DataStrings
8) Key Macros * life will be easier if you read this!
9) Expressions * life will be easier if you read this!
10) MultiBin Files
11) Screen Icons Reference
12) Keyboard Reference
13) Mouse Reference * life will be easier if you read this!
14) Menu Reference
15) Process Variables Memory
16) Grabbing An Existing Process
17) Auto Trace Mode
18) Hardware Monitor * only for those who know...
19) 68020 Modes/Instructions
20) Installing To Hard Drive
21) Contact Address * when you've decided to register...
* ------------------------------------------------------------------------- *
1) Introduction
===============
Welcome! Now, I know what you're thinking... 'I can't be bothered
reading all these dox!'. Well, I'm sorry, but eventually you're going to have
to do so. To try and make things easier, I've commented the contents (above)
to try and steer you in the right direction to begin with. After that, read
either whatever you need to, or whatever you're interested in. And, it goes
without saying, but if at all possible, get a copy of this file printed!
Disect is a very powerful combined disassembler/debugger program,
which has been designed to be easy to use. Its power is achieved at the
expense of memory: the minimum requirement is 1Mb; for larger projects, 2Mb
will be required. The programmer neither encourages nor condones its use to
assist in illegal duplication of copyright software. Disect can be used for
two main purposes: development of software; and the gaining of knowledge
(hacking can be very educational).
The debugger allows an executable file, a disk boot-block, a
binary file, or an area of memory to be loaded and created as a Process. It
is even possible to grab an existing memory-resident Process. A Process's
instructions can be executed individually, or the Process can be activated,
with or without breakpoints installed. System exceptions can be trapped
before they crash the machine, and program symbols can be read from execut-
able files.
The disassembler allows a loaded program to be commented, have
blank lines inserted, and have it's numbers and addresses replaced with
constant or program symbols. All the symbols of Release 3 of the system
include files are available to the disassembler. A program which has been
dissected in this way can then be saved as two source files: a program file,
and a support file. The support file will contain EQUs for all required
constant symbols. System constant symbols can be EQUs (grouped by the SI file
where they live), or alternatively the support file can INCLUDE all required
SI files. Disect data files can be saved, to be reloaded later: 'hold on to
your hacks'!
Disect requires Release 2 of the Amiga operating system; it also
requires the ASL library.
If you've paid your shareware fee then you'll have the full
version. Otherwise, the copy you've got is (hopefully) only a demo. This
has a few differences: you cannot disassemble to file; you cannot extract
program symbols from executable files. In addition, you will not have all of
the system symbol data files. If this is so, and since, as I don't doubt,
you'll be impressed by this program, then don't hesitate in registering
today, by sending your name and full address, and a cheque/postal order for
£30, to the address which you'll find at the end of this file. As well as
receiving a registered version, you'll also be entitled to technical support
(by mail) if required. If you like this program, it's well worth the money.
'Disect' is Shareware, Copyright © D.M.Alderson 1994/5, all
rights reserved. Duplication for the purpose of backups is permitted, but
not for the purpose of selling or otherwise distributing the software,
manual, or other related items, which includes '.dsct' data files only for
commercial purposes, without written permission from the author. This does
not apply to the demo version of the software, which in such instances would
include the manual, and other related items, but not including '.dsct' data
files unless for commercial purposes.
The author does not make any warranty, express or implied, with
respect to the software or any related item, their quality, performance, or
fitness for any purpose. It is the responsibility solely of the purchaser
to determine the suitability of the software for any purpose. In no event
will the author be liable for incidental or consequential damages of any kind
in connection with the software product, manual, or other related items and
processes including, but not limited to, any interruption of service, loss of
business, anticipated profit, or other consequential damages. ETC.
Disect was written using a 2 meg A500+ (without a hard drive! -
will people PLEASE hurry up and register?)
* ------------------------------------------------------------------------- *
2) Disect Request Windows
=========================
The program takes much of its input through 'request windows'.
These are standard windows containing string and button gadgets, etc. The
more commonly used windows have keyboard shortcuts. Where available, these
consist of the first letter of the text within the gadget (which will be
underlined). One exception is the 'Select Address Base' request: to select
'+ Decimal' you use key 'p'; to select '- Decimal' you use key 'm'.
Many of the windows allow specification of a number of address
ranges (eg: when searching memory). These contain a list of the currently
defined address ranges, and two string gadgets to input the start and end
addresses (inclusive) of a range. You should input the start, and then the
end, after which, if the range is ok, the address range will be stored. Note
that you may not enter zero as an address. For most of the windows, the
ranges list will be initialised to contain the start and end addresses of
any loaded project memory. If you LMB on any address range, it will be
selected, and can then be changed. If you select a range, then enter no
input for the start and end addresses, the range will be deleted from the
list. The RMB can be pressed to un-select a selected address range.
Instead of having to enter the actual end address into any end
address string gadget, it is possible to instead enter the size of a memory
area, by preceeding it with a comma. You can also enter, for example: '+12',
which will result in an address range of 13 bytes (ie: end address = start
address + 12). For an address range of a single byte, you can simply enter
'='.
Be aware: it is essential to always press Enter when entering
a number or expression into any string gadget, especially during definition
of a key macro.
One last thing: if Disect seems to lock-up, try pressing any
SHIFT key, or any ALT key, or the CTRL key.
* ------------------------------------------------------------------------- *
3) The Program Screen
=====================
As of V1.2, Disect incorporates menus for most functions. To
prevent contention between menus, and Disect's use of the RMB, in order
to select from a menu, you must first RMB click on the menu bar, in order
to 'activate' the menus. To disable the menus, and allow Disect to respond
to the RMB in the main window, you simply LMB on the window, away from the
menu bar (for example, on the status/message area).
At the top of the screen is displayed the available chip and
fast memory, various function icons, and the program's status/message output.
The status message consists of the current state of any Process (--- none,
-S- Process suspended, -A- Process active, -W- Process Wait()ing), info of
any defined disassembly window markers, and the number of address stack
entries. The icons (from left to right) are: unused; auto-data; address
stack (3 icons); INCBIN; workbench screen; disassembly window left/right
scroll arrows. See below for more info.
Below this is the disassembly window area. There can be either
one or two disassembly windows open at once: the tab key will toggle between
single and double window mode. The cursor keys can be used to scroll windows,
while pressing shift also will move a window faster. In double window mode,
pressing the left alt key will select the lower disassembly window. This
applies to the cursor keys as well as other disassembly window keys (eg: A,
F1-F9, F10).
In each disassembly window, you'll find up and down arrow gadgets
for scrolling the window. Normally, these work upon the window in which they
are situated. It is possible, however, to use either pair of arrow gadgets
to scroll the memory window, by also pressing the right ALT key.
Next down is a window which displays the PC and SR values, and
the source effective address (SEA) and destination effective address (DEA) of
the instruction at the PC, when applicable. Also displayed is the content
of these addresses. There are two lines of this: the upper line displays
the current values, while the lower line displays the previous values. This
allows the SEA/DEA content to be seen to be affected after execution of an
instruction, which is not possible with programs which display only the
current values. The upper line can be used to enter new values for the PC
and SR, via LMB on the digits of the PC, or the digits/letters of the SR.
To enter a new SR value, a request window will be opened. This allows input
of either an expression (denary/hex/binary/symbols), or any combination of
the letters XNZVC to denote which flags are to be set: any unspecified flags
will be cleared. If no input is received, then the PC/SR is unaffected. If
the Process is active, then attempting to change the PC or SR will have no
actual effect.
The third line in this window is the 'register zoom'. This can
be locked to any of the registers d0-d7 or a0-a7, and displays the register
content, and the content of this address and the next 15 bytes upward in
memory, as denary/hex (depending on the currently selected base), and as
ascii characters. The '·' character is displayed for any bytes not within
the ascii range of 32 to 127. The locked register is selected by LMB on the
text of 'd0', 'd1', etc in the register window. The register zoom can also
be locked to the SEA or DEA of the instruction at the PC, if a Process has
been created, by LMB on the text of 'sea=' or 'dea=' in the first line of the
window.
The register window is the lower-left window on the screen, and
this displays the register values as denary/hex. For data registers, the
register content is displayed also as ascii. For address registers, the
register content is also used as an address; the content of this is displayed
as denary/hex and ascii. Any of the registers can be given new values in the
same way as the PC, by LMB on the digits of the register value. A nice little
feature which you may at times find useful is, when entering for an address
register value, instead of an address, you may enter, for example:
>a text string
This has the effect of storing all the input text after the '>' character,
and setting the address register to point to the stored text. Disect contains
eight such text buffers, each of which may contain up to 63 characters.
The lower-right window is the memory dump. This can be scrolled
using cursor keys and the right alt key. The shift key applies for the up
and down cursor keys as it does for the disassembly window. By LMB on the
address digits, you can input a new address for any of the separate lines in
the window. When you do this, the addresses of any lines below the affected
one will be updated, but any above it will remain unchanged. This allows, for
example, the first line to be locked on one memory location, the second to be
locked on another, and the remaining six lines to be used as a memory dump
starting from yet another address. If you use the cursor keys to move the
window, the first two lines will stay where they are in memory, and only the
continuous block of six lines will be moved. Neat eh? Note that a much bigger
memory dump window can be accessed by pressing 'm'.
If you have a Process, then try this now: enter the following
into the address area of the first line: PROCP. This will move the window
to the Process structure; the fields of this structure are displayed using
(abbreviations of) the structure field names.
* ------------------------------------------------------------------------- *
4) A Disassembler Tutorial
==========================
The best way to understand something is to do it, so on the disk
you'll find an executable file called 'KeepASL' (in the Tutorial drawer).
This is a little utility I wrote ages ago since I was fed up with having to
reload the ASL after each time I assembled something. All it does is to open
the ASL library and the clipboard device, preventing them from being removed
from memory. So load up Disect, and select 'Load Executable' from the project
menu.
The next request allows you to define whether or not to create a
Process, and extract any symbols from the executable file. Leave these un-
checked (you don't need to create a Process for the disassembler, and there
are no symbols in 'KeepASL'). The string gadget allows you to enter any CLI
arguments to be passed to the executable file (again, not required now). So,
just LMB on 'OK'.
The executable will be loaded, and the disassembly window moved
to it's start address. Note that marker 9 will be defined at the address -
marker 9 is always defined at the start address of any loaded executable/
binary/boot, etc. When you load a binary file, marker 8 will be defined at
its end address, so if you were to save the binary file later, you could
enter 'm9' for the save binary start address, and 'm8' for the end address.
Next, if you haven't already done so, load the SysSymbol data for
the following directories: DOS, EXEC, INTUITION. This is done by pressing the
'Help' key to access the 'Resident SysSymbol Data Preferences', selecting the
required data, then 'Use'. This request also allows you to load and save the
preferences, or to quit, which will restore the preferences to the state they
were when you pressed 'Help'.
In the disassembly window, you'll have something like this:
0000665256 move.l 4.w,665604
0000665264 bsr.w 665504
0000665268 lea.l 665766(pc),a1
0000665272 moveq.l #0,d0
0000665274 movea.l 665604(pc),a6
0000665278 jsr -552(a6)
0000665282 move.l d0,665608
0000665288 beq.w 665406
0000665292 lea.l 665784(pc),a1
0000665296 moveq.l #0,d0
0000665298 movea.l 665604(pc),a6
0000665302 jsr -552(a6)
0000665306 move.l d0,665612
Obviously, the addresses will be different but the methods are the same.
First of all, LMB on the area between the address and the mnem-
onic of the first line, and enter the text 'main'. From the request window,
select 'Instruction'. This will define a program symbol for the first address
of the program, and will log the address as an instruction. Incidentally, if
you ever enter a program symbol name which does not fit into the available
area, the end of the name will not be lost. On the screen, only the first 11
characters will be visible; when you disassemble to a file, the whole of the
name will be output.
Now, LMB on the destination effective address of the first line.
This will open the symbol selection window (see below for specific info).
Activate the string gadget which presently contains the LMB'd address, and
enter the text 'sys_base'. From the request windows which open, you should
define the address type as 'Variable', the address size as 'Long', and the
address base as '+ Decimal'. What this does is to log the DEA of the first
instruction as a long variable, the content of which will be displayed as
positive (unsigned) denary. Just to make sure, RMB on the DEA of the first
line, and you'll see:
0000665604 sys_base DC.L 0
The previous disassembly window address will have been stacked (look at the
status message), so you can return there either by LMB on the third icon
from the left at the top of the screen, or by pressing F10. Do this now!
You'll notice that as well as having replaced the DEA of the
first line with the program symbol 'sys_base', Disect will also have replaced
all other references to this address. This feature can be disabled by press-
ing 'Del', and unchecking 'AutoSymbol', BUT DON'T DO THIS NOW!
Now, to make the source more readable, we'll add a blank line
after each of the following lines in the disassembly window: the first, the
second, and the eighth line. Do this by LMB on the mnemonic of each of these
lines. This will open the 'Address Functions' request, from which you should
select 'Add Blank Line' (at lower-left of window). For the second and eighth
lines, you'll get the 'Address Type' request, since these addresses have not
yet been logged - obviously, these should be logged as instruction addresses.
This will result in the following:
0000665256 main move.l 4.w,sys_base
0000665264 bsr.w 665504
0000665268 lea.l 665766(pc),a1
0000665272 moveq.l #0,d0
0000665274 movea.l sys_base(pc),a6
0000665278 jsr -552(a6)
0000665282 move.l d0,665608
0000665288 beq.w 665406
0000665292 lea.l 665784(pc),a1
0000665296 moveq.l #0,d0
Next, LMB on the text '-552' (or -$228), then on the text 'exec'
in the lower window. You'll probably have guessed already, but LMB on the
text '_LVOOpenLibrary' in the upper window, then select 'Confirm', and define
the address as 'Instruction'. Now, we all know that a call to exec.Open-
Library() requires a1 pointing to the library name text, so RMB on the SEA of
the third line. What you now see won't look like much, until you've done the
following: define a program symbol at the first line in the disassembly
window, 'name' will do, and define the address as Data/Byte/ASCII/0. Now
we know what library it is, we can change the program symbol from 'name' to
'int_name':
0000665766 int_name DC.B "intuition.library",0
The last request window ('Select Data Area Size') allows you to
define how many bytes there are in a data area in five ways: you can enter
an expression to define the number of BYTES; you can simply press 'Enter' to
make it consist of one byte, one word, or one long (depending on the address
size already defined); you can select '0' to make the data area end at the
first NULL byte/word/long; you can select '-1' (end at first -1 byte/word/
long); or you can select 'Symbol' to make it end at the byte before the
address of the next defined program symbol.
If you now press F10, you'll see that the address reference will
have been replaced with 'int_name'.
Next, press the 'A' key, and enter the following: '[0:$58]'. This
will move the disassembly window to the $58th byte of the first hunk. Here,
you will see a 'jsr' as the third line. LMB on the text '-204' or '-$cc',
and replace it with '_LVOOpenWindow'. So, the first line contains the address
of a NewWindow structure, so RMB on this address to move the disassembly
window to this data. Now press key 'X', (or select 'Define DataString' from
the 'Functions' menu), and from the list of system DataStrings, LMB on the
text 'NewWindow', then select the 'Define' gadget. The NewWindow structure
data area will be logged, and Disect will inform you that it has found an
address pointer within the NewWindow structure, which points to an ASCII
string. Click on the 'Define' gadget, and the ASCII string will also be
defined as a data area. The disassembly window will now be returned to the
address of the NewWindow structure. For further information about DataStrings
I STRONGLY recommend that you read section 7.
Well, we could go on like this for all of the 560 bytes of the
program, but fortunately, you don't have to. Instead, select 'Load DSCT Data
File' from the project menu, 'Erase', then load the file 'KeepASL.dsct':
; * -------------------------------------------------------------
; Disassembly of 'KeepASL' - DMA 1.10.94
0000665256 main move.l (EXEC_BASE).w,sys_base
0000665264 bsr.w start_up ; WB/CLI start up
0000665268 lea.l int_name(pc),a1 ; open intuition
0000665272 moveq.l #0,d0
0000665274 movea.l sys_base(pc),a6
0000665278 jsr _LVOOpenLibrary(a6)
Much better than the original, eh!
Now, we're going to disassemble the whole program to source, so
press 'd'. This gives the 'Disassemble To File' request. The disassembly
address range will be initialised as the address range of the loaded program.
Note that with executable files, there may be more than one hunk in the file,
so it is possible to disassemble more than one address range. Now, using the
two string gadgets at the bottom of the window, enter the two path/file names
as 'RAM:Program.s' and 'RAM:Support.s', then select either to EQU or INCLUDE
system constant symbols (I suggest EQU), and select 'OK'.
After a short time a request window will open, informing you that
an immediate long has been found. This means that Disect has found a number,
as immediate data, which is within the project memory range. It is possible
for such numbers to be immediate data, or program addresses, but it should
be fairly obvious for you to decide which from the context in which they are
used. For such numbers, Disect will display any matched program symbol name,
or alternatively, the previous program symbol to the address along with the
required offset to match the value of the number. From this request, you have
a choice of leaving the number as immediate data, replacing the number with
the symbol (or symbol+offset), or quitting the disassembly process.
In our case, the number should be replaced (it's actually the
nw_Title pointer of the NewWindow structure). Ok, when it's done, load up
the two source files (you'll actually find them in the Tutorial drawer,
although I suggest you DO have a go at all this). Have a look at them...
Nice, aren't they! AND, they'll assemble correctly.
* ------------------------------------------------------------------------- *
5) Symbol Selection Window
==========================
A major feature of Disect is its ability to replace numbers
present within a program with symbols. Disect can distinguish between two
different types of symbols:
PROGRAM A program symbol refers to a specific address within the program.
This may be either the destination of a branch, etc, or an access
to a variable, or the address of data.
There are two kinds of program symbol, system and user. System
program symbols, or system address symbols, are used to refer to
absolute addresses in memory, for example, the addresses of chip
registers. These form part of Disect's predefined system symbol
list. User program symbols are defined by the user, and are used
to refer to addresses within the program being disassembled.
CONSTANT A constant symbol refers to any number used as immediate data, or
as a displacement for the following addressing modes:
ARID dd(ax) ARIDI dd(ax,rx.x)
PCD dd(pc) PCDI dd(pc,rx.x)
Disect's predefined system symbol list includes all of the system
constants of Release 3.0 of the system include files. These are
divided into three classifications:
LVO a library vector offset used with: jsr dd(ax)
Structure a system structure offset used with: dd(ax)
Constant all other system symbols
User constant symbols are defined by the user. There are three
different types of these: normal constant symbols; constant symbols which
represent offsets from a Process's variables-memory base address register
('variable constants'); and 'address constants'. Address constants are
temporary symbols which make it easier to see what a Process is doing. For
example, if a Process calls Inituition.OpenWindow(), on exit, d0 will point
to the Window structure. Obviously, you cannot define a program symbol for
this address (outside project memory), but if you were to then press the
'CTRL' key, and LMB on the 'd0' text in the register window, a request
window will open into which you can enter a symbol name, eg: 'WINDOWP'.
Now, whenever any register contains the address of this symbol, then this
name will be displayed in the register window instead of the address.
A valid symbol name must begin with either a letter, or the
characters '_' or '.', and may continue with any of these, as well as digits.
Disect supports the use of local program symbols, which must be prefixed
with either a '_' or '.' character, depending upon the current preference
setting. There are a certain number of reserved symbol names which cannot
be used when defining a symbol. The list of these can be found in section 9.
In order to replace a number within a program, all you have to
do is LMB on the number in the disassembly window. This will open the Symbol
Selection Window, which is used to specify which symbol(s) are to be used to
replace the number. In addition to using real symbols, Disect also allows
'fake' symbols to be created. These are symbols which have no name text.
Instead, the 'name' is the value of the symbol displayed in whatever base you
select. For example, instead of replacing the number 16 with the real symbol
'MP_SIGTASK', you could replace it with the fake symbol '%10000'. Or, the
number 65 may be replaced with a fake symbol: "A". The possible bases for
fake symbols are decimal, hex, ASCII, binary. Such symbols will appear in
the symbol list where appropriate.
Whenever you replace a number, the address where the number
occurs becomes logged in the usual way. In addition, if you are replacing
an address with a (new, program) symbol, then this address is also logged.
Consider the following:
632472 move.l 632804,d0
~ ~ ~
632804 ori.b #0,d0
If you LMB on the '632804' in the first line, and replace it with a symbol,
eg: 'variable', then the addresses of both lines will be logged. First,
Disect will allow you to define the address type for the equivalent address
of '632804' (although INCBIN is not supported in this way, at present). In
this example, it might be address type: VARIABLE/LONG/... This will log the
second address, and assign to it a program symbol (named 'variable'). After
this, the Symbol Selection window will close, and Disect will then request
the characteristics of the first address (INSTRUCTION).
The Symbol Selection window contains two list windows. The left
window will display the current list of matched symbols. You may select a
symbol from the list by LMB on it within this window. The right window will
display either a list of system include directories, or a list of the files
within a selected directory. You can LMB on a directory or file name in order
to limit the symbol search to only the selected directory or file. If you RMB
on a system constant symbol (in the other list), then this will select the
system include directory and file which contains that symbol. Note that if
you RMB anywhere else (not in the symbol list window), then the current list
of symbols will be sorted alphabetically.
The currently selected system include path is displayed above the
includes list window; to the right of this text is a 'Parent' gadget to un-
select the current directory and file names.
In the symbol list window, if a symbol has a '*' character disp-
layed after its name, then this denotes that the symbol is not defined in
the official system includes. There are quite a few of these to allow greater
flexibility. They include 'FLAGB_' and 'FLAGF_' definitions of 680x0 process-
or flags (in exec/execbase.i), and a complete list of raw key codes (devices/
keyboard.i), as well as some hardware bits symbols. When disassembly to file,
any such symbols will be output to the support file as EQUs.
Above the symbol list window, are four gadgets. The first two
gadgets allow selection of the type of symbol to be searched for. The first
gadget selects between System or User symbols; the second, between Program or
Constant symbols.
The third gadget allows you to select the type of search to be
performed; there are two possible types of symbol search: Value, and Bit.
The first will search all resident symbols for a direct value match with the
number to be replaced. A Bit search will list all symbols for which a set
bit in the original number corresponds to a set bit in the symbol's value.
This is used when replacing a number which represents bitwise OR of multiple
bit flags. As examples:
move.l #IDCMP_RAWKEY+IDCMP_CLOSEWINDOW,(a0)
move.w #DMAF_MASTER+DMAF_COPPER,dmacon(a5)
When searching for symbols in this way, when you have selected the first
symbol to be used, Disect will then only list symbols which represent bits
in the same group of flags (eg: only IDCMP_ flags, or only DMAF_ flags).
The fourth gadget depends on the current symbol type: for program
symbols, a 'Prev' gadget will exist; for constant symbols, an Offset cycle
gadget will exist.
The 'Prev' gadget will automatically select the system/user
program symbol with a value previous to that of the number being replace
(which would be an address). This is useful for finding, for example, a
reference to the low byte of a word variable (assuming you have already
defined a program symbol for the address of the word), or a refernce into
a data table. It becomes especially useful if replacing a system address:
for any direct address reference to a hardware register, pressing this
gadget will result in the symbol 'CUSTOM_BASE' being automatically selected
(ie: address $DFF000). The apprioriate symbol from the hardware directory
(custom.i) can then be selected to account for the required offset to the
actual address. When you attempt to find a previous (user) program symbol,
Disect will only use a local program symbol if this does not result in a
reference to a local program symbol across the bounds of a global program
symbol.
When searching for system/user constant symbols, the Offset cycle
gadget will be displayed. This allows you to select an offset value to be
used when searching for a symbol value match. The possible offsets are:
-1, -2, -3, +1, +8, +16, +24. Such an offset represents the value to be added
to the original search value in order to find the value to which the symbol
search must match symbols. For example:
btst.b #INTB_AUD3,intreqr(a5)
Now, INTB_AUD3 has the value 10, ie: bit 10 of the word-register. When this
is assembled (some assemblers would allow the above, some would require you
to have '-8' after the 'INTB_AUD3'), the resulting code would actually be:
btst.b #2,$1E(a5)
So, when you LMB on the '2' in the disassembly window, obviously Disect would
search for symbols of value 2. If you've already replaced the '$1E' with
'intreqr', then you'll be expecting an 'INTB_' symbol. This would return
'INTB_SOFT'. Incorrect. Hence, an offset of '+8' will solve the problem, and
produce the relevant result (by searching for symbols of value 2+8, hence
'INTB_AUD3' would be found!). The actual result would, of course, be:
btst.b #INTB_AUD3-8,intreqr(a5)
Above the four symbol gadgets is a string gadget which is used
for displaying the current search value, or the current list of selected
symbols
Above the four symbol gadgets is a string gadget. This has a dual
purpose of displaying the currently selected list of symbols which will be
used to replace the number, and to allow a symbol name to be input. When
searching for user program or constant symbols, you may enter any valid
unused symbol name here, and this will be created as a new user symbol which
will be assigned the value of the replace-number.
If you enter the name of an existing system/user symbol, then
this will have the effect of selecting the symbol. In this case, the symbol
search value (ie: originally the number which was being replaced), will be
adjusted to take account of the value of the symbol which you entered. This
is useful since there are times when a number being replaced is formed from,
for example, an accumulation of structure offsets. As an example, consider a
program which allocated it's variables memory dynamically, then accessed them
using ARID mode via a5. Supposing this memory block was 2k in size, and you
have determined that bytes 240 to 273 are used for an MP structure (message
port, exec/ports.i), so you have defined a user constant symbol 'mport' to
have the value 240. Now, you might find the following:
move.b 255(a5),d0
What this represents is in fact:
move.b mport+MP_SIGBIT(a5),d0
This can be achieved by entering the name 'mport' (which will be selected,
and the search value of 255 adjusted to 15), then selecting the 'MP_SIGBIT'
symbol by LMB in the symbol list window.
To the right of the string gadget are three check gadgets which
are used to select the type of symbols to be searched for when searching for
system constant symbols. These gadgets will automatically define themselves
according to the context where the replace-number was used. Note that this
cannot be 100% accurate for the type of symbols: always make sure you are
searching for what you want!
Whenever a symbol is selected which results in the search value
becoming zero, then a request window will open. The content of this varies.
If you are making a normal symbol selection (due to LMB in the disassembly
window), then four gadgets will exist: 'New' 'Zero' 'Confirm' and 'Quit'.
When making a dummy symbol selection (due to pressing the 'P' key in the main
window), then a 'Comment' gadget will exist instead of 'Confirm'. If you are
replacing a number within a bitfield instruction (ie: either the offset or
width value), then you get 'New' 'Confirm' and 'Quit'.
The 'New' gadget will erase the currently selected symbol(s) and
allow a new seclection to be made. 'Zero' will allow you to select further
symbols (of value 0). 'Confirm' will cause the original number in the disass-
embly window to be replaced with the currently selected symbol(s). 'Quit'
will abort, and close the Symbol Selection window. The 'Comment' gadget has
a rather useful purpose (see key 'P' in section 12).
* ------------------------------------------------------------------------- *
6) Address Functions
====================
The Address Functions request is accessed via LMB on the opcode
(mnemonic) area in the disassembly window. The address functions are as
follows:
Log Address
-----------
This allows a program address to be logged. You will be requested
the type of the address. This may be instruction, variable, data, copper,
INCBIN, ASCII string (NULL-terminated), or EVEN string (which is the same,
except Disect will ensure that the string ends at an odd address, so that
the next address is therefore even). Note that any extra pad byte used to
word-align the string must be NULL. If a Process exists, then when an address
is logged (by any method), if the PC is at the address, then it will be auto-
matically defined as an instruction address.
INSTRUCTION This is the default address type for all addresses at which the
opcode can be successfully identified as a valid instruction.
VARIABLE This allows an address to be defined as a byte, word, or long
variable. The base in which the variable's value should be
displayed can also be defined.
DATA Similar to a variable address, a data address consists of any
number of bytes, words, or longs. The size of the data area can
be specified by either: pressing Enter (for 1 byte/word/long);
inputting an expression to determine the number of bytes of data;
selecting the '0' or '-1' gadget (data continues up to & includ
-ing the first 0 or -1 byte/word/long); or selecting the 'Symbol'
gadget (data area continues until next defined program symbol).
Incidentally, there is another way of defining data areas. See
section 7.
COPPER A copper address will be disassembled as a macro which, when
assembled, will create the relevant copper instruction. These
macros will be output to the support source file during file
disassembly (if required). Note that for copper move instruction,
if the hardware SysSymbol data is resident then the move destin-
ation address will automatically be replaced with the relevant
symbol for the hardware register it refers to.
INCBIN This allows data areas to be defined as INCBIN areas. Such areas
will be disassembled as an INCBIN directive. Upon selection of
this, Disect will request the INCBIN data area size. After this,
the ASL is used to select the file to which the data area should
be written. See also the section about the INCBIN request window.
ASCII The data area will be defined as an ascii string, terminated by
a NULL byte.
EVEN STRING As ASCII, but is guaranteed to be even.
AS PREVIOUS This will automatically define an address of the same type, etc,
as the previously defined address. Be careful not to use this
after, for example, defining an address via the Symbol Selection
Window, since this would be taken as the previous address type.
Amend Address
-------------
This allows a previously-logged address to be amended.
Erase Address
-------------
This will remove anything that has been attached to the address.
Add/Erase Section Header
------------------------
A section header is a line of '-' characters, which will be added
before the address.
Add/Erase Header Comment
------------------------
These options allow a full-line comment to be added before the
address, or to be removed from the address.
Add/Erase Line Comment
----------------------
These allow an end-of-line comment to be added to the address, or
removed from the address.
Add/Erase Blank Line
--------------------
These will add/remove a blank line after the address.
Erase Program Symbol
--------------------
This allows a program symbol to be removed from the address.
Erase SEA Symbols
-----------------
This option will remove any symbol(s) which have been used to
replace the instruction's source effective address. This includes the offset
and width values for 68020 bit fields.
Erase DEA Symbols
-----------------
This option will remove any symbol(s) which have been used to
replace the instruction's destination effective address. This includes the
offset and width values for 68020 bit fields.
* ------------------------------------------------------------------------- *
7) DataStrings
==============
In order to log a data area which consists of a number of byte/
word/long elements, ie: all bytes, all words, OR all longs, you use the
address functions request. This allows you to specify the total size of the
data area, and Disect will log only the first address. Obviously, this can
save a lot of memory for large data areas, since Disect does not have to
store information for each address. This is the best way of logging uniform
data areas.
For any data area where its elements are not all the same size
(byte/word/long), you can use a DataString. The DataString request, accessed
via key 'X', allows you to define your own DataString, or select a system
DataString, and use it to define a data area.
A DataString consists of two strings: the format string, and the
base string. The first specifies the size of each element of a data area;
'B' represents a byte, 'W' a word, and 'L' a long. The base string defines
the base of a 'piece' of data: 'P' positive denary; 'N' negative denary;
'H' hex; 'B' binary; 'A' ASCII; 'X' means use the currently selected default
base (either hex or denary, as defined via the preferences). When you use
a DataString to define a data area, successive addresses are logged as data,
the size and base of which corresponds to the relevant characters from the
format and base strings.
Disect contains a number of predefined (system) DataStrings. The
names of these correspond to the names of system structures, eg: Gadget, New-
Window, etc. Each DataString represents the byte/word/long elements of the
relevant system structure. You can also define your own DataStrings, which
will be saved/loaded as part of the Disect data file. In the DataString
request window, after pressing Enter in the base string gadget, if your
DataString is valid, then it will be automatically stored. The LMB can be
used to select a DataString from the currently displayed list.
As of V1.6, when you use a system DataString to define a data
area, a preference exists to allow Disect to automatically add a line comment
to each 'DC.X' directive. These comments will be the names of the fields of
the system structure which the DataString represents.
When you later LMB on the operand of such a 'DC.X' directive (in
order to replace it with a symbol) then Disect actually uses the line comment
text in order to define which system include file is to be searched within
the Symbol Select window. If the required directory's SysSymbol data is not
resident, Disect will attempt to load it. As well as automatically selecting
which include file, Disect also defines which 'group' of bit symbols should
be listed, if necessary. For example, if you LMB on the number of:
DC.W $44040 ; nw_IDCMPFlags
then the Symbol Select window will open in 'intuition/intuition.i', and only
'IDCMP_' flag symbols will be listed! If required, once such a number has
been replaced with a symbol, Disect will automatically erase the line comment
text since it is no longer required. This is a preference, and can therefore
be disabled if necessary. In addition, an item exists in the 'Functions'
menu which will erase ALL existing SDS (system DataString) line comments.
When defining an data area using a system DataString, Disect can
detect pointers to other system structures. For example, within a NewWindow
structure, nw_FirstGadget will be detected as pointing to a Gadget structure.
In this case, Disect will move the disassembly window to the address of the
Gadget structure, and a request window will open which allows you to confirm
to Disect that you wish the data area to be defined, or alternatively, you
can cancel the definition.
The window also contains a string gadget, which will contain
either the text of any existing program symbol at the start of the data area,
or a symbol name which Disect will create automatically. Whichever, this is
the symbol name which will be defined for the first address of the data area.
It is not possible to enter any other program symbol name. For example, for a
Gadget structure, Disect may create a program symbol of 'gadget0'. The number
at the end of the symbol name is defined to be unique for each data area
definition. It is recommended that you use these automatic symbol names
(see below).
Whenever a data area is defined in this way (due to a pointer to
it within a previously-defined data area), then the program symbol of it is
used to replace the number/address within the existing data area. Example:
DC.L gadget0 ; nw_FirstGadget
~ ~
~ ~
~ ~
gadget0 DC.L $13ef26 ; gg_NextGadget
Two of the system structures which are supported by DataStrings
exist as an array of structures. These are TagItem and NewMenu structures.
When you define a data area for either of these structures, Disect will also
define any following structures, until the end of the array. For example,
a TagItem array ends when ti_Tag holds a value of TAG_END.
One last point to mention is that when a data area is defined via
a system DataString (directly from the request window, as opposed to via a
pointer to it in a previously-defined data area), if the first address of the
area does not have a program symbol, then Disect will automatically create
one for the address, as described above. The thing to be aware of is that
when disassembling to a source file, Disect has the ability to detect such
program symbols, and if it does so, it will disassemble the data area using
a single macro (instead of a sequence of DC.X directives). For example:
gadget1 DC.L gadget2
DC.W 326,4,50,14
DC.W GFLG_GADGHCOMP,GACT_RELVERIFY,GTYP_BOOLGADGET
DC.L border12,0,intuitxt7,0,0
DC.W 2
DC.L 0
The above would automatically be converted to:
gadget1 GADGET gadget2,326,4,50,14,GFLG_GADGHCOMP,GACT_RELVERIFY,
& GTYP_BOOLGADGET,border12,0,intuitxt7,0,0,2,0
This will not occur: if any address in the data area has a line end comment;
if any address in the data area other than the first address has either a
header comment, or a program symbol; or if you have not used Disect's auto-
matic symbol names. The syntax for continuing macro parameters over more than
one line follows that required by Devpac. Any required macro definitions
will be output to the Support source file.
As a result of this feature, any program symbol name which might
be created by Disect is now reserved; this means that you cannot use these
names for any other program symbols you might create. The complete list of
reserved symbol names (and macro names) can be found in section 9.
The DataString request window contains the following:
Data Start Address
------------------
A string gadget allows the data start address to be specified.
This will be initialised, when the window opens, to be the start address of
the (upper) disassembly window.
DataString Name
---------------
A string gadget is used to enter the name of a user DataString.
If you enter the name of an existing DataString, it will be selected.
Data Format String
------------------
This string gadget allows you to enter up to 512 characters to
specify the format of the data area. Each data element may be specified to
be byte, word, or long, by entering the characters 'B', 'W', or 'L'. Note
that if you enter, for example, 'LLBBBW', then Disect will automatically
insert an extra 'B' before the 'W' to ensure word-alignment. Disect will
permit an odd number of 'B' if it is at the end of the string.
Data Base String
----------------
This string is used to enter an equal number of characters to
specify the base of each data element. Each may be any of: 'P' positive den-
ary; 'N' negative denary; 'H' hex; 'B' binary; or 'A' ASCII.
Associated with each string are two numbers. The first displays
the number of characters for each string. The second displays the number of
successive, same, characters at the end of each string.
System/User Cycle
-----------------
This will toggle between a list of system and user DataStrings.
Delete
------
This will delete the currently-selected user DataString.
Define
------
This will close the window, and cause Disect to attempt to define
the data area using the selected DataString. If an error occurs, the disass-
embly window will be moved to the address which Disect was attempting to log
when the error ocurred. Where possible, Disect will preserve any existing
program symbols and comment texts within the definition data area. Any blank
lines will be removed, but one will be added at the end of the data area.
Quit
----
This will close the window, without defining the data area.
* ------------------------------------------------------------------------- *
8) Key Macros
=============
The 'Macros' menu allows up to ten key macros to be defined and
used. This allows sequences of key presses, LMB or RMB clicks, and gadget
and menu selections to be recorded, and played back automatically by pressing
a single key. As an example of just how useful this can be, supposing you
were dissecting a program which contained a data table of, say, a hundred
entries, each one consisting of the following sort of thing:
DC.B "some text string",0,0
DC.L program_function67
Before this has been logged as data, it might be disassembled as, for
example:
$42be8 DC.W $736f
$42bea blt.b $42c51
$42bec DC.W $2074
$42bec bcs.b $42c68
~ ~
~ ~ etc
To define a key macro to format a single entry, first of all you would make
sure that the disassembly window is at the start address of the first entry.
You then begin the macro definition by selecting the menu item 'Macros/Begin
Definition/Macro 1'. First, by LMB on the first 'DC.W', you would define the
address as an 'EVEN String'. This gives:
$42be8 DC.B "some text string",$0,$0
$42bfa ori.b #$0,-(a0)
Next, LMB on the 'ori.b', then select 'Add Blank Line', and define this
address as a single 'Data/Long/Hex' long. Finally, by clicking on the
disassambly window down arrow twice, then pressing 'Enter', the macro will
be defined. By moving the disassembly window down two lines, you will ensure
that each time you use the macro, the relevant addresses will be formatted,
since the macro has been defined to operate upon the first two lines in the
disassembly window. All that is now required is to press the '1' key to use
the macro to define successive entries in the data table, until the end of
table is reached.
During definition or playback of any macro, if any errors occur,
then the macro definition/playback will be aborted. This would result in a
macro NOT being defined. This also occurs if any Process exception occurs;
this includes trace and breakpoint exceptions: macros are not compatible
with Process execution.
Remember! When defining a key macro, you must always press Enter
for all string gadgets which you use!
A defined macro can be replayed either by pressing it's key
(1-0), or using the menu item. Via the menu item, a request window will
open which allows you to specify either to play the macro once, to play the
macro a specific number of times, or to play the macro until an expression
is TRUE. This is probably most useful for something such as the following:
'w1=$662084', which would play the macro until the (upper) disassembly
window reached a certain address.
Macro playback can be aborted by clicking on the main program
window, and pressing Escape.
* ------------------------------------------------------------------------- *
9) Expressions
==============
Disect allows complex expressions to be input whenever a numeric
value is required. Such expressions may contain program or constant symbols,
which may be system or user symbols, although local program symbols are not
permitted. Numbers may be expressed as denary, hex, binary, or character
constants (eg: 'a', "ab", 'abc', "abcd"). In addition, addresses can be
represented as offsets from hunk/project memory starts. For example, the
text "[0:16]" represents the address of the 16th byte of hunk 0 (the first
hunk). If there is only one project memory area (eg: an executable of only
1 hunk, or a binary file, has been loaded), then a hunk number does not have
to be specified ("[16]" would be accepted). Any numbers within the "[]"
characters may be either hex or decimal. If a base offset address has been
defined, then if you were to input "[16]", then this would be taken as an
offset from the base offset address (instead of as an offset from the start
of the first/only hunk).
It is also possible to prefix a number with a '.', for example:
'.$80000046'. This will cause Disect to treat the number as an FFP value,
which in this case would be evaluated to a value of 32. If the value is too
large/small to be stored as a long integer, then an error will result.
Disect supports the following operators, in decreasing order of
precedence:
HIGH PREC - MINUS, eg: -32
~ bitwise NOT, eg: ~$0FF0
<< >> SHIFT LEFT and RIGHT, eg: %1<<16
& ! ^ bitwise AND, OR, EOR
* / \ MULTIPY, DIVIDE, MODULO
+ - ADD, SUBTRACT
= < > <> <= >= comparisons
Precedence may be overridden via parentheses ( and ). Expressions
are evaluated left-to-right. Byte, word, and long indirection is supported
via parentheses:
{4}.l long content of address 4
The following is also possible:
{{4}.l}.w word content of address specified by
long content of address 4
The comparison operators return the value 0 if FALSE, and -1 (or
$FFFFFFFF) if TRUE. Expression evalution occurs using 32-bit unsigned integer
arithmetic. The operator | is equivalent to ! (bitwise OR); != may be used
for <> (inequality).
There also exists a number of reserved symbol names. Unlike all
other symbols, they are case-insensitive:
M1-M9 disassembly window markers 1-9
W1 start address of upper/single disassembly window
W2 start address of lower disassembly window
W3 start address of memory window
If any address register is equal to any of these, then the relevant name
will be displayed in the register window instead of the actual address:
BASEEXEC Exec library base address
BASEDOS DOS library base address
BASEGFX Graphics library base address
BASEINT Intuition library base address
BASEASL ASL library base address
BASEGADT GadTools library base address
BASEMFFP MathFFP library base address
The following are only valid if a Process exists:
D0-D7 current value of data registers
A0-A7 current value of address registers
PC current value of program counter
SR current value of status register
CCR current value of condition codes register
SP current value of a7
SEA source effective address of instruction at PC
DEA destination effective address of instruction at PC
INITSP value of a7 when Process initially entered
PROCP address of Process's Process structure
If the trackdisk device has been opened (via the Functions menu), then the
following symbol name will evaluate to the address of the IOExtTD structure:
IOEXTTDP
In addition, Disect will not allow symbol names such as 'A235768', or
'a23ff40', since such names may be automatically created during disassembly
to file, and hence should not exist already.
The following lists all the symbol names reserved for creation
of automatic program symbols for system structure data areas which have been
defined via DataStrings. Each symbol name is the base name to which an ascii
number is added. All possibilities (actually, an infinite number) of each
base name text are reserved. The macro name is the name of the macro which
is used to disassemble the whole data area during disassemble to file (note:
macros are used only if the program symbol at the start of the data area has
not been changed since the data area was defined).
System Structure Base Symbol Macro Name
---------------- ----------- ----------
BB bblock BOOTBLOCK
BitMap bitmap BITMAP
BoolInfo boolinfo BOOLINFO
Border border BORDER
ColorSpec colrspec COLORSPEC
EasyStruct easystru EASYSTRUCT
ExtGadget extgadg EXTGADGET
ExtNewScreen extnscrn EXTNSCREEN
ExtNewWindow extnwind EXTNWINDOW
Gadget gadget GADGET
Hook hook HOOK
Image image IMAGE
IntuiText intuitxt INTUITEXT
KeyMap keymap KEYMAP
LH listhead LISTHEAD
LIB lib LIBRARY
LN listnode LISTNODE
MC memchunk MEMCHUNK
ME mementry MEMENTRY
MH memheadr MEMHEADER
ML memlist MEMLIST
MLH minlisth MINLISTHEAD
MLN minlistn MINLISTNODE
MN message MESSAGE
MP messport MESSAGEPORT
Menu menu MENU
MenuItem menuitem MENUITEM
NewGadget newgadg NEWGADGET
NewMenu newmenu NEWMENU
NewScreen newscrn NEWSCREEN
NewWindow newwind NEWWINDOW
Process process PROCESS
PropInfo propinfo PROPINFO
StringExtend strextnd STREXTEND
StringInfo strinfo STRINFO
TTextAttr ttxtattr TAGTEXTATTR
TagItem tagitem TAGITEM
Task task TASK
TextAttr textattr TEXTATTR
TextFont textfont TEXTFONT
TextFontExtension tfontext TEXTFONTEXT
* ------------------------------------------------------------------------- *
10) MultiBin Files
==================
The 'Save MultiBin' item in the 'Project' menu allows a single
binary file to be created which consists of more than one block of memory.
The item will open a request window which contains a list of entered address
ranges, string gadgets for entering address ranges, and a couple of gadgets
at the bottom of the window.
The 'SegList' gadget allows a memory-resident SegList to be
used to automatically define the address ranges to be saved. By entering
the start address of the first hunk in memory into the string gadget next
to the 'SegList' gadget, and then clicking on the 'SegList' gadget, Disect
will scan the SegList, and store the start and end addresses of each hunk
in the SegList. Be careful! The address to be entered as the start address
of the first hunk should be the address at which the PC begins when the
SegList is executed (the SegList is immediately before this address in
memory). Note that using the seglist gadget will cause the two longs before
each hunk to be saved in the MultiBin file. Whenever you save a MultiBin by
entering the address ranges yourself, do not forget to account for these
longs (since they may be referenced by the Process).
There is also a check gadget which will force the file which is
saved to be pure binary. In general, if you have used the 'SegList' gadget,
then this should be unchecked, since extra information is saved in the file
which enables the MultiBin file ('.mbin') to be reloaded later to the same
addresses from which each block of memory was saved, and possibly created as
a Process. This is of most use when dissecting an executable which allocates
memory, into which it decompresses the real program as a complete SegList.
By specifying the initial execution address of the first decompressed hunk,
the complete program can be saved as a MultiBin file.
If the gadget is checked, then only the exact content of the
specified memory ranges is saved, as a binary file ('.bin'). This means that
the saved memory cannot be loaded back later to the exact addresses from
which each block was saved.
The 'Load MultiBin' item in the Project menu allows a previously
saved MultiBin file to be loaded. This presents a request window which has
an 'Allocate Saved Memory' check gadget. If checked, then Disect will attempt
to load the MultiBin file to the exact addresses from which it was saved.
Alternatively, if unchecked, the file will be loaded to any available memory.
A separate executable program called 'AllocMultiBin' allows the
required memory of a MultiBin file to be allocated. It should be used immed-
iately after re-booting your machine. It will open an ASL requester with
which you specify the MultiBin file to be loaded. If an error occurs, the
program will re-open this requester; if the file loads successfully, the
program will merely wait until you click on it's window's close gadget, and
will then free the memory used by the MultiBin file (although normally you
would NOT do this).
Once the MultiBin file has been loaded, you should leave 'AMB'
in memory, and load Disect. Then select 'Load MultiBin' from the 'Project'
menu, select the same MultiBin file as was loaded by 'AMB', and check the
'Allocate Saved Memory' gadget in the relevant request window. From this
window, click on the 'OK' gadget, and 'AMB' will automatically free the used
memory, then terminate, allowing Disect to load the MultiBin file to the
required memory.
Also in the Save Multibin request window is an 'Add' gadget,
which will attempt to add a selected address range to the current project,
if the memory is available.
As of V1.8, Disect allows a single MultiBin 'file' to consist
of more than one file, across a number of disks. This is governed by the
preference 'Max MultiBin Size'. This is only needed by floppy disk users,
(me!) since it is possible to require MultiBin files of more than 800k.
This preference is only a general limit, since Disect will not split user-
defined memory areas.
In addition, it is also now possible to save the state of your
Process in a MultiBin file. This is used when dissecting games (ie: anything
which does not use the OS), since obviously any opened windows,etc cannot
be saved. Disect will save the current registers (d0-d7/a0-a7/pc/sr), the
state of the hardware monitor (without the Pre-/Post-Execute functions),
and the Process's stack. One thing to be aware of is that if the Process's
stack top address has been defined (see the section on the Hardware Monitor),
then the stack memory is not saved, since this memory will already be part
of the project memory.
* ------------------------------------------------------------------------- *
11) Screen Icons Reference
==========================
Here is information about the icons at the top of the main
program screen, from left to right across it.
Unused Icon
-----------
This icon is not used at present.
Auto-Data Icon
--------------
This is a 'cycle' gadget which will be in one of four states: '-',
'B', 'W', or 'L'. When '-', its function is disabled; otherwise, by LMB on
the mnemonic of an instruction in the disassembly window, Disect will auto-
matically define the relevant address as data (a single DC.X), which will
be either byte, word, or long. The base of the operand will be that which
is currently selected (hex, or decimal).
Address Stack Icons
-------------------
The address stack is used in order to follow the flow of a prog-
ram. If the RMB is pressed over an address in the disassembly window, the
current window start address will be stacked, and the disassembly window will
be moved to the new address. The three icons are: retrieve last stacked
address, stack current disassembly window address, and delete last stacked
address. Note that if pressing left alt while RMB, the lower disassembly
window address will be stacked/changed.
INCBIN Icon
-----------
This icon will access the INCBIN request. This allows you to
define data areas which are to be disassembled using an INCBIN assembler
directive. In order to define an area, you simply enter the start and end
addresses of the area, and, if these are valid, Disect will then ask you to
select the file to save the binary area as. If the file is written ok, then
the INCBIN area will be defined.
You can select an existing INCBIN area by LMB in the address
ranges list window. In order to delete an INCBIN area, you select it, then
enter NULL strings for the start and end addresses (ie: empty the string
gadget, and press 'Enter'). An INCBIN area may be unselected by pressing
the RMB.
The 'Save' gadget is used in order to re-save, or rename, an
existing INCBIN area's binary file. This is only achieved by selecting
an INCBIN area first.
The 'ILBM' gadget will open the ILBM request window. This allows
a selected INCBIN area to be saved as an IFF ILBM file. The window contains
two string gadgets to allow the size of the ILBM to be specified in pixels,
a cycle gadget to select the depth of the ILBM (up to 6 bitplanes), two check
gadgets to select the view modes (hi-res/interlace), and six bitplane-select
gadgets. These are used to select which bitplanes a selected INCBIN area
contains. You can either specify that the INCBIN area contains a single
bitplane, in which case you would click on the relevant bitplane gadget.
Alternatively, you can specify that the INCBIN contains all of the required
bitplanes as defined by the currently selected ILBM depth. In this case, you
merely click on the 'All Planes' gadget at the bottom of the window. When
a bitplane has been defined, its gadget will contain the number of the bit-
plane (1-6). If you click on the gadget again, it will cycle through the
characters 'S', 'C', and '-'. These represent a fully set or a fully clear
bitplane, and an undefined bitplane, respectively. The 'New' gadget will
erase the current bitplane definitions, allowing a new selection to be made.
WorkBench Icon
--------------
This allows the workbench screen to be opened/closed.
Arrow Icons
-----------
The upper pair of left and right arrow icons can be used to move
the upper disassembly window; the lower pair are for the lower disassembly
window (if this is open). By also pressing the right ALT key, either pair
can be used to move the memory window.
* ------------------------------------------------------------------------- *
12) Keyboard Reference
======================
This section contains general program information, related to
the keys which invoke each feature of Disect. The complete list is below:
Windows Cursor Keys Move upper disassembly window
-------
& LEFT ALT Move lower disassembly window
& RIGHT ALT Move memory window
& SHIFT Move window fast
A {LEFT ALT} Define disassembly window address
F1-F9 {LEFT ALT} Go to disassembly window marker
SHIFT F1-F9 {LEFT ALT} Define disassembly window marker
F10 {LEFT ALT} Retrieve last address stack entry
ESCAPE Refresh all windows
+ Swap both disassembly window addresses
\ Address/Offset display mode
TAB Single/double disassembly window
QUOTE (above TAB) Change number base (hex/decimal)
Y Move disassembly window to previous addr
U Move disassembly window to next address
O Move disassembly window after data area
Functions F Search memory
--------- G Continue search
W Fill memory
Q Copy memory
S Display symbols
D Disassemble to file
I Display information
H Display processor history
M Display memory dump
Z Evaluate expression
X DataStrings (see section 7)
P Dummy symbol selection
DEL Display preferences
HELP Display resident SysSymbol preferences
ESCAPE Abort search/disassemble to file
Process E Execute instruction (whole of JSR/BSR)
------- T Trace instruction (stops inside JSR/BSR)
C Breakpoint after PC & resume
V Breakpoint at PC DEA & resume
N Next instruction (without execute)
K Kill Process
B Define breakpoint
L Kill breakpoints
DISASSEMBLY WINDOW ADDRESS (A)
==============================
This opens a window through which to input the required address.
If the left alt key is pressed with the 'A' key, then the input will be used
to define the lower disassembly window address.
DISASSEMBLY WINDOW MARKER (F1-F9)
=================================
With the shift key, keys F1 to F9 will define disassembly window
markers 1 to 9 at the current disassembly window address. To delete a marker,
both keys can be pressed a second time. Without the shift key, the disass-
embly window will be moved to the address of the selected marker. If the left
alt key is also pressed, then the lower disassembly window will be used.
RETRIEVE STACKED ADDRESS (F10)
==============================
Key F10 will retrieve the last stacked address and move the dis-
assembly window to it. Again, left alt can also be pressed to move the lower
disassembly window.
REFRESH MAIN WINDOWS (ESCAPE)
=============================
As well as refreshing all windows in the main program screen,
the escape key will, if a Process exists, move the (upper) disassembly window
to the current PC address (if this address is not visible in a disassembly
window).
MOVE TO PREVIOUS ADDRESS (Y)
============================
This will move the disassembly window to the previous logged
address from the first logged address in the disassembly window. Left alt
will select the lower disassembly window.
MOVE TO NEXT ADDRESS (U)
========================
This will move the disassembly window to the next logged address
from the first logged address in the disassembly window. Left alt will select
the lower disassembly window.
MOVE AFTER DATA AREA (O)
========================
This will move the disassembly window to the address after the
first logged data address in the disassembly window. This is useful in order
to pass large (uniform) data areas.
SEARCH MEMORY (F,G)
===================
Key 'F' will open the Search Memory request window, with which
you can define the ranges of memory to be searched, the type of search data,
and the data to be searched for.
At the top of the window are two string gadgets to input the
start and end addresses (inclusive) of a range. You should input the start,
and then the end, after which, if the range is ok, the address range will be
stored. Note that you may not enter zero as an address. The current ranges
are displayed in a window below these gadgets. To the right of this window
are gadgets to scroll through the list of address ranges. This list will be
initialised to contain the start and end addresses of any loaded project
memory. If you LMB on any address range, it will be selected, and can then
be changed. If you select a range, then enter no input for the start and end
addresses, the range will be deleted from the list. The RMB can be pressed to
un-select a selected address range. Note that this info applies to all other
windows where address ranges have to be specified.
The gadgets at the bottom of the window are used to select the
type of search. This may be byte, word, long, ASCII, or source. The string
gadget allows input of the search data. For byte/word/long, this must be a
sequence of expressions, with a comma to separate each parameter. For ASCII/
source, the text string entered is the search data. Note that ASCII will
search memory for a text string, while source will actually disassemble the
specified address ranges, and compare the resulting source with the input
text. Obviously, searching for source is slower. The case gadget allows you
to specify whether to ignore case when searching for ASCII/source. If check-
ed, then Disect will use case-sensitive search; if unchecked, then case will
be ignored.
If searching for byte/word/long, you may enter a single '?' char-
acter instead of an expression, in order to specify that a search-element is
unknown. For example, if you entered 32,"A",?,16 for a byte search, then the
following would be successfully matched: 32,65,46,16 and 32,65,12,16... etc
When searching for ASCII/source, the '?' character may be used in the same
way. In order to specify a search for a '?' character, you must enter '??'
instead. When searching for ASCII or source, any number of spaces input as
the search data will be matched to any number of spaces (or tabs) during the
search.
Key 'G' will continue a search which has been halted due to the
search data being found. If searching for byte/word/long or ASCII data, then
Disect will move the memory window (screen lower right) to the address where
the search data has been found. If searching for source, then the (upper)
disassembly window will be moved instead.
Note that no checks are performed on the memory areas: if you
(accidentally?) read from hardware registers, etc, you'll probably regret it...
An alarm sound will begin whenever the search data is found, or
when the search ends (data not found).
In order to specify the end of an address range, it is possible
to enter the following into the 'End' string gadget:
= specifies an address range of a single byte (ie: the
end address is the same as the start address) - most
useful for Fill Memory (!)
+X specifies an address range of (X+1) bytes (ie: the
end address is the start address + X; 'X' can be
any valid expression)
,X specifies an address range of X bytes; 'X' can be
any valid expression
This is possible in all request windows which allow input of an address
range. (Search Memory/Fill Memory/Copy Memory/INCBIN/Load Memory/Save Binary/
Disassemble To File)
FILL MEMORY (W)
===============
This opens the Fill Memory request window, which is similar to
Search Memory (above). The fill data type may be byte, word, long, or ASCII.
Note that no checks are performed on the memory areas: if you (accidentally?)
write to hardware registers, etc, you'll probably regret it...
COPY MEMORY (Q)
===============
A window will open, allowing you to specify the start and end
addresses of the source memory area, and the start address of the destination
memory area. These two areas may overlap without any corruption occurring.
Note that no checks are performed on the memory areas: if you (accidentally?)
write to hardware registers, etc, you'll probably regret it...
DISPLAY SYMBOLS (S)
===================
This will open a window via which a list of all current user
symbols is displayed. At the window top is displayed the total number of
program and constant symbols. The gadgets at the bottom of the window allow
selection of whether to list program, constant, variable, or unused symbols,
and the order in which to list the symbols (either alphabetically, or by
increasing symbol value - NOTE that to resort the symbol list, you must
also press the RMB).
The next two gadgets allow you to delete or rename a selected
symbol. A symbol may be selected by LMB on it. Once a symbol has been
deleted, it cannot be retrieved. To rename a symbol, you should select it,
press the 'Rename' gadget, enter the new name into the string gadget which
is automatically activated, then press Enter.
There is also another gadget, 'VM'. This allows a constant symbol
to be changed to a variable symbol, and vice versa. See 'Process Variables
Memory' for more info.
As of V1.2, if you LMB on a program symbol which has already
been selected, then the symbol window will be closed, and the (upper)
disassembly window will be moved to the address of the symbol.
As of V1.3, if you press a letter key (with or without a shift
key), or the ".", or "_" keys, then, if the symbols have been sorted alpha-
betically, the window will move to the first symbol beginning with that
character.
DISASSEMBLE TO FILE (D)
=======================
Use of this feature is described in the tutorial (above); here is
some specific information.
The disassembly process occurs in two passes. On the first pass,
Disect disassembles the required address ranges internally, creating a list
of all referenced addresses which have not had a program symbol created for
them, a list of all required system symbols, and a list of all required user
symbols. Any immediate long numbers which lie within the disassembly address
range(s) which have not been replaced by a symbol are also checked for.
Also, during the first pass, Disect performs checks for any local
program symbol references across the bounds of a global, For example:
some_sr bsr .do_it
rts
another_sr bsr elsewhere
.do_it jsr miles_away
If any such references are found, Disect will move the upper disassembly
window to the reference of the local program symbol, and the lower window
to the address of it. Disassembly to file will be abandoned.
Disect will also warn you of any references to address which lie
within project memory range, but which are outside the disassembly range. If
one is found, a request window is opened which contains three gadgets:
'Ignore' will resume disassembly, and cause the referenced address to be
stored in a permanent list so that if the address is referenced again (either
during the current, or any subsequent, disassemble to file), then Disect will
know not to bother telling you about it. The item 'Clear External Address
List' in the functions menu will erase the current list of these addresses.
'Ignore All' will resume disassembly, and Disect will not inform you of any
external referenced addresses.
'Quit' will...
On the second pass, the disassembly occurs again; this time the
program and support source files are created. Now, any address references for
which no program symbol exists will have automatic symbols written for them.
For example, the following code:
0000675372 lea 683208,a0
~ ~ ~
~ ~ ~
0000683208 DC.W 10
would be disassembled as:
lea A683208,a0
~ ~ ~
~ ~ ~
A683208 DC.W 10
After the whole disassembly is complete, there may still be some referenced
addresses which were not disassembled directly. For example:
0000675372 move.w 683208,d0
~ ~ ~
~ ~ ~
0000683206 data_table DC.L 10
0000683210 DC.L 20
Here, the first line would have been disassembled containing 'A683208', but
there would be no program symbol of this name. Instead, any missing address
references will be output to the end of the program file, by offsetting them
from the previous global program symbol. As an example, the code above would
result in:
A683208 EQU data_table+2
If Disect finds a data area where all bytes are NULL, instead of
creating lots of 'DC.X 0' source, Disect will convert the source to a single
line of 'DCB.X n', where n=the required number of bytes/words/longs. This
will not occur if the first line of the data area (ie:the only logged address
of the data area) has had it's DC.X operand (a zero!) replaced with a symbol,
or if the line has a line comment.
During disassembly to file, Disect will concatenate multiple
lines of DC.B, DC.W, or DC.L statements to form (much) fewer lines of source.
Also, when outputting system or user constant EQUs, Disect will group them
using their prefix, in numeric order. For example:
SYMB_FIRST EQU -32
SYMB_SECOND EQU 0
SYMB_FOURTH EQU $10
The disassemble to file request window also contains gadgets:
'Project' will define the disassemble address range list to match the current
project address ranges.
'Clear' will clear the address range list.
'Load' and 'Save' allow a ('.dfr') ascii file to be loaded/saved to be used
as the address range list.
And last, but not least, any defined disassemble to file address
ranges will be displayed in the disassembly window as background colour 3
(blue, if you've not changed your WB prefs).
DISPLAY INFORMATION (I)
=======================
The displayed information contains the number of logged program
addresses, and the number of program and constant user symbols. Below this
is displayed the address range and size of each project memory area, with the
type of the memory (C=chip, F=fast, P=public).
DISPLAY PROCESSOR HISTORY (H)
=============================
After any instruction is traced or executed (or skipped via key
'N' - see below), or whenever an active Process reaches a breakpoint, or
whenever an exception occurs, the current processor state is stored. This
information is accessed via the processor history display. The most recent
entry is displayed in the lower window, with previous entries above. The
display of register contents is in hex, although by LMB on the digits of a
number, its value is displayed in denary in the small box in the top left of
the request window. The thing to note is that for any entry, the register
values represent the values after executing the previous instruction, while
the PC, SEA/DEA and instruction disassembly represent the next instruction
to be executed.
DISPLAY MEMORY DUMP (M)
=======================
This opens a large memory dump window, the start address of which
will be initialised to the current address of the first line of the small
memory window in the main program screen. The window may be moved around
memory using the cursor keys (and the shift key to move it faster). A string
gadget in the window top left allows a new start address to be input. The
base of the address digits will be the same as the currently selected base
for the main program screen (denary or hex). Note that the ASCII display will
show the character '·' for any memory locations for which the content is out-
side the ASCII range of 32 to 127.
By LMB on a memory location's content, Disect will display the
denary values of the byte, word, and long starting at that address. The cycle
gadget in the window allows you to select whether to display the B/W/L as
signed or unsigned denary.
RMB on a memory location's content will cause the Base Offset
Address to be defined at the address of the selected byte. The preferences
will also be updated to display offsets instead of addresses.
EVALUATE EXPRESSION (Z)
=======================
This opens a window containing a string gadget for input of an
expression. The current string content will be evaluated whenever Enter is
pressed. Expression results are displayed as unsigned denary, signed denary
(if the sign bit is set; ie, either bit 31, bit 15, or bit 7 depending upon
whether the value is in the long, word, or byte value range - try it out with
results of 4294967295, 65535, and 255 - you'll see what I mean!), hex, ASCII,
binary, and any program symbol if one is found of the result value.
DUMMY SYMBOL SELECTION (P)
==========================
This will request a single expression, the result of which will
be passed to the Symbol Selection Window. This allows you to select symbol(s)
in the usual way, for any number, although obviously no information will be
stored about your selection. When a symbol match occurs, the window will
display the 'New', 'Zero', and 'Quit' gadgets as usual, but the 'Confirm'
gadget will be replaced with a 'Comment' gadget. If this is selected, then
the Symbol Selection window will close, and a message will appear in the
main window. By LMB on the mnemonic of an instruction within the disassembly
window, the actual text of the selected symbols can be automatically stored
as a line comment for the instruction. The comment text will automatically
have the chars "*!*" added to the end, allowing such comments to be found
in disassembled a source file, using a text editor. As an example, if a
program routine allocated temporary space for definition of a NewWindow
structure:
link a5,#-48
Although you cannot replace '-48' with 'nw_SIZE', by making a dummy selection
for a value of '48', the Symbol Selection window will list 'nw_SIZE'. By
selecting this, then the 'Comment' gadget, the symbol text is stored as
a comment (with a marker allowing it to be found and edited, when a source
file has been disassembled).
DISPLAY PREFERENCES (DEL)
=========================
This window allows selection of program preferences. The gadgets
at the bottom of the window allow the last saved preferences to be loaded,
the current settings to be saved, the current settings to be used, and the
previous settings to be restored (ignoring any changes since window opened).
The preferences are as follows:
AutoSymbol This enables/disables automatic symbol replacement. This means
that as addresses are disassembled via display of the disassembly
window(s), any address which has not been replaced by a program
symbol will automatically be replaced by any program symbol which
has a matching value. In addition, if the 'hardware' directory
SysSymbols are resident, then any references to chip registers
or CIA addresses will also be automatically replaced. This also
includes the bit number of a btst/bset/bclr/bchg when the DEA
is any of CIAA_PRA, CIAB_PRA, or CIAB_PRB. Also, any instructions
of the form 'jsr dd(a6)' will have their displacements replaced
with _LVO symbols, if a6 contains the base address of any of the
libraries: Exec, DOS, Graphics, Intuition, ASL, MathFFP, GadTools.
This only occurs if a Process exists, and will take place when
the instruction at the PC is a jsr. This preference also controls
Process Variables Memory references symbol replacement (see
elsewhere).
Auto 0(Ax) This enables/disables automatic display of a '0' before '(Ax)'
for the address-register-indirect addressing mode. This is useful
because some assemblers will automatically optimise address-
register-indirection-with-displacement references to ARI if the
displacement is zero. This feature allows a '0' to be displayed
so that it can then be replaced with a symbol (for example:
exec/lists.i 'LH_HEAD' which has the value 0).
Case This allows selection of upper or lower case for disassembly.
Note that assembler directives will always be disassembled as
upper case.
Base This allows selection of denary or hex for disassembly.
A7/SP This allows selection of 'a7' or 'sp' for disassembly.
Local This allows selection of the character to prefix local program
symbols. This may be either '.' or '_'.
PSymb ':' This enables/disables automatic display of a ':' character after
program symbols in the program symbol field of a line.
SAD This enables/disables automatic display of program symbols
instead of addresses in such places as register values, memory
dump addresses, addresses in request windows, etc.
Offset This allows addresses to be displayed as hunk/project memory
start offsets instead. If selected, any address which lie within
the project memory range will be displayed as, for example,
"0:256", where 0 is the hunk number, and 256 is the offset.
In the disassembly window, this will be enclosed in "[]" chars.
In addition, you may define a base offset address (using an item
from the preferences menu). If you do this, then ALL addresses,
not just addresses in project memory range, will be displayed
as offsets relative to the base address, eg: "-$32", or "[+146]".
A small request window is used to define the base address. This
contains a string gadget for input of the address, and a check
gadget to enable/disable the current base address.
Comment DS This enables/disables automatic line comments when Disect defines
a data area using a system DataString.
Erase DSC This enables/disables automatic removal of DataString-defined
line comments after symbolic replacement of a number.
Blank Lines This preference enables/disables automatic blank lines. If used,
Disect will add blank lines after any of these instructions:
DBcc, Bcc, JMP, JSR, RTD, RTE, RTR, RTS.
Process Mem This informs Disect whether or not to install a memory monitor
when a Process is created (not if a Process is grabbed). If one
is installed, then when the Process terminates, a request window
will open to list any unfreed memory allocations. Disect will
display the start and end addresses of each memory block, as well
as the size. Also displayed will be either: 'SELF' if the memory
was allocated by a function within the Process; the name of the
library containing the function which allocated the memory (if
this can be determined); 'ROM' if the memory was allocated by a
ROM function which could not be named as a library. If the alloc-
ator cannot be determined, then the return address when AllocMem()
was called will be displayed. Any unfreed memory which is shown
as being self-allocated is automatically freed by Disect.
The memory monitor is installed by calling Exec.SetFunction() for
the functions AllocMem() and FreeMem(). Before doing this, Disect
first checks the current destination addresses of their JMP inst-
ructions (the jump table just below ExecBase). If either of these
instructions do not jump to a ROM address, then Disect will not
attempt to install the memory monitor. Note that it is necessary
to install a memory monitor for certain features of the Auto
Trace mode (see elsewhere).
MaxMBinSize This allows you to specify the maximum size of each file of a
MultiBin file. See the specific section about MultiBin files for
more info.
MaxSourceSz This allows you to specify the maximum size of a source file
when disassembling to file.
DISPLAY SYSSYMBOL PREFERENCES (HELP)
====================================
As mentioned above, this window allows selection of resident
SysSymbol (system symbol) data. The four gadgets at the bottom of the window
work as for Preferences (above). Response to changing the preferences occurs
when the window is closed. Note that you cannot remove a directory's data
from memory if it is used (ie: if any of it's symbols are used by the project
in memory). The digits after each directory's name represent the size of the
data file. It's best not to load data without using it, since any resident
data is checked in such circumstances as expression evaluation, checking if
a symbol name is used already, etc.
EXECUTE INSTRUCTION (E)
=======================
Only available if a Process exists, this will execute the single
instruction at the PC. Note that the whole of a JSR/BSR will be executed, ie:
the Process will be suspended at the address after the JSR/BSR instruction.
Any permanent breakpoint at the PC will be ignored.
One small point to add is that it is possible to execute PC-
relative JSR/BSR instructions which use 68020 specific address modes, even
with a pre-68020 processor. (The reason: JSR/BSR instructions are buffered
before execution, so therefore PC-relative modes get changed to absolute-
long address mode. In the case of BSR, the instruction is changed to JSR
absolute-long, so therefore any BSR which uses an 020 mode is permitted
on a pre-68020 processor. If you didn't follow that, it does not matter...)
TRACE INSTRUCTION (T)
=====================
This will trace the instruction at the PC, if a Process exists.
This means that if the instruction is a JSR/BSR, then the Process will be
suspended at the first instruction of the subroutine which is called. Any
permanent breakpoint at the PC will be ignored. In addition, if you trace
a JSR or a BSR, then any form of breakpoint at the PC is ignored.
RESUME PROCESS (Process Menu)
=============================
This will activate a suspended Process, hence it and Disect will
be running 'simultaneously' (multi-tasking). Any permanent breakpoint at the
PC will be ignored during the (first) execution of the instruction there.
BREAKPOINT AFTER PC (C)
=======================
This will define a stop breakpoint after the instruction at the
PC, and resume the Process. This is useful if the instruction is a DBcc/Bcc,
since an entire program loop may be executed, and the Process suspended after
the loop has been completed the required number of times. A permanent break-
point at the PC will be ignored during the (first) execution of the instruc-
tion there.
BREAKPOINT AT DEA (V)
=====================
This will define a stop breakpoint at the DEA of the instruction
at the PC, and resume the Process. This, again, is useful for executing
program loops, but ones where the exit point of a loop does not sequentially
lead to the next instruction. Any permament breakpoint at the PC will be
ignored during the (first) execution of the instruction there.
NEXT INSTRUCTION (N)
====================
This will move the PC to the next instruction without executing
the current one. Any breakpoint at the PC will be ignored.
KILL PROCESS (K)
================
This will kill a suspended Process. This is achieved by changing
the Process's stack pointer to the address it was when the Process began,
moving the PC to an RTS instruction, and resuming the Process.
Whenever a Process terminates, if any data exists, you will be
given a chance to save it before it is (automatically) erased.
DEFINE BREAKPOINT (B)
=====================
This allows a breakpoint to be defined. The program requests the
address of the breakpoint, and it's type. This may be permanent, conditional,
stop, or count. Conditional breakpoints also require an expression. This will
be evaluated after input, and if no error occurs, the breakpoint will be
defined. Whenever execution of an active Process reaches a conditional break-
point, then its expression will be evaluated. If the result is not zero, then
the breakpoint is removed, and the Process suspended. If the result is FALSE
(equal to zero), then the Process is resumed. If the expression cannot be
evaluated (for example, due to an unknown symbol name), then the Process will
be suspended, with the breakpoint intact, and an error message displayed.
Count breakpoints have associated with them a long counter. When-
ever the breakpoint is reached, the counter is decreased. If it reaches zero,
then the breakpoint is removed, and the Process suspended, otherwise the
Process will resume.
Stop breakpoints are simple breakpoints which will cause the
Process to be suspended. They are removed whenever encountered. Stop break-
points are in fact count breakpoints with an initial counter value of 1.
Note that an alternative method of defining a breakpoint is to
LMB on the address digits in the disassembly window, at the address where the
breakpoint is required.
When an active Process reaches a breakpoint, if the breakpoint
causes the Process to be suspended, then the PC will be at the address of
the breakpoint, and the instruction there will not yet have been executed.
Whenever an exception occurs, the PC will either be at the address of the
instruction which caused it, or at the address of the next instruction.
KILL BREAKPOINTS (L)
====================
This will remove all currently-defined breakpoints. It works even
when the Process is active.
* ------------------------------------------------------------------------- *
13) Mouse Reference
===================
This section describes the areas of the main program screen which
will respond to LMB or RMB activity.
Disassembly Window
------------------
1) Address Digits LMB at left of window to define breakpoint. #
2) Address Digits RMB at left of window to remove breakpoint.
3) Program Symbol area LMB define program symbol for the address.
4) Program Symbol area RMB on a local moves window to its global.
5) Mnemonic LMB to access address functions.
6) Mnemonic RMB to move PC to instruction.
7) Number LMB in instruction operands to replace with symbol(s).
8) Program Address RMB in instruction operands to stack current
address and move window to new address. *
9) Displacement RMB in instruction operands to stack current
address and move window to EA, eg: 32(a6). *
# Right ALT may also be pressed, which will move the memory window to the
address instead of defining a breakpoint.
* Left ALT may also be pressed to move the lower disassembly window; right
ALT may be pressed to move the memory window (in which case, no address
will be stored on the address stack).
PC/SR/EA Window
---------------
1) PC Value Digits LMB to define new PC value.
2) SR Value Digits/Flags Text LMB to define new SR value.
3) SEA/DEA Text LMB to select register zoom lock.
4) SEA/DEA Value Digits RMB to display previous program symbol.
Register Window
---------------
1) D0-D7/A0-A7 Value Digits LMB to define new register value.
2) D0-D7/A0-A7 Text LMB to select register-zoom lock.
3) D0-D7/A0-A7 Text LMB and CTRL key to define an address
constant symbol (see section 5).
Memory Window
-------------
1) Address Digits LMB to define new memory display address.
The following request windows also have responses to mouse buttons:
Memory Dump
-----------
1) Memory content LMB to display byte/word/long value as denary.
2) Memory content RMB to define base offset address.
Breakpoints Window
------------------
1) Breakpoint information LMB to move (upper) disassembly window.
Symbol Window
-------------
1) Symbol name LMB (twice) to move (upper) disassembly window.
* ------------------------------------------------------------------------- *
14) Menu Reference
==================
This section details any program functions which are accessible
only via menus (no keyboard commands), and are not documented elsewhere.
SAVE BOOT BLOCK (Project Menu)
==============================
This allows an area of memory to be saved as a boot-block. (Very
handy for making your favourite game a little more enjoyable!). Note that
the boot-block checksum will be defined by Disect.
SCAN '.GS' FILE (Project Menu)
==============================
This allows a '.gs' file as produced by GenAm to be scanned, and
its constant symbols extracted. When doing this, if Disect finds a symbol
name which is already used (either by a system or a user symbol), then the
values of the two symbols are compared. If they both have the same value,
then the symbol from the '.gs' file is ignored. If the values differ, then
a request window will open, allowing you to either rename the symbol from
the '.gs' file (type in the new name, and press 'Enter'), or to ignore the
symbol from the '.gs' file (click on the 'Ignore' gadget). Note: it is best
to scan a '.gs' file ONLY AFTER you have already loaded any required system
symbols for your current project. This is because when SysSymbol data is
loaded, no checks occur for existing symbol names. When you later save your
'.DSCT' data, the symbols read from the '.gs' file will also be saved, so
you only need to scan a '.gs' file once.
INSERT BINARY FILE (Project Menu)
=================================
This allows a binary file to be loaded into current project
memory.
SEARCH FOR SYMBOL (Functions/Memory Menu)
=========================================
This allows a very fast search for the use of any system or user
symbol. After you have entered the required symbol name, if this is known by
Disect, then a search of all logged addresses is performed to see if this
symbol has been used to replace any number within the project.
EQU SYMBOL DEFINITION (Functions Menu)
======================================
This allows manual definition of a constant symbol.
SET SYMBOL DEFINITION (Functions Menu)
======================================
This allows manual definition of a constant symbol which can be
redefined later to have a different value. Quite useful when using macros
for certain things...
PLAY AUDIO SAMPLE (Functions Menu)
==================================
This opens a request window which allows specification of the
start and end addresses of an area of memory to be played as an audio sample.
Once a sample has been identified, it can be saved as a raw/binary file.
OPEN TRACKDISK DEVICE (Functions Menu)
======================================
This allows the trackdisk device to be opened (DF0:), and used
for disk IO if required by a Process. Typically, this is required when you
have loaded a boot-block, then later saved your project as a multibin file.
When this is later re-loaded, you can open the trackdisk device in order to
execute the code of the original boot block. If opened, then a reserved
symbol name becomes valid ('IOEXTTDP'), which gives the address of the
required IOExtTD structure. There is also another menu item which will
turn off the drive motor (very useful in certain circumstances).
EXECUTABLE BINARY OFFSET (Functions Menu)
=========================================
This strangely-titled function has a very specific use. Suppose
you have loaded an executable file into memory, and have decided you want
to patch, for example, a NOP into address [2:$2438] (ie: the 3rd hunk, offset
$2438). What is required is to erase the project, then re-load the executable
as a binary file, so that it exists in memory as a single block of code,
which can be changed and re-saved. But! Obviously, address [2:$2438] could
be very difficult to find within this single block.
This function solves this problem. It has two ways of being used,
depending on the type of the current loaded project. If an executable has
been loaded, you will be requested to enter a hunk number and offset, which
Disect will use to scan the original executable file on disk, in order to
display the offset into the file of the required byte.
If a binary file has been loaded (ie: an executable file loaded
as a binary file), you will again be requested to enter a [hunk:offset], and
Disect will move the disassembly window to the required byte within memory.
BREAKPOINT AT ACTIVE PROCESS PC (Process Menu)
==============================================
This allows Disect to regain control of an active Process. In
terms of Exec task-switching, the Process will be either Wait()ing on signals
or Ready (suspended only until its next quantum). If the Process is Waiting,
then the breakpoint will be defined, but the Process will remain Waiting
until it receives a valid signal (caused by, eg: LMB on it's window), at
which point it will reach the breakpoint.
If the Process is Ready, then the breakpoint can only be defined
if the Process's PC is within project memory range (ie: not within ROM, or a
system library, etc).
Note! This function is very handy if your Process goes into an
infinite loop!!
DISPLAY BREAKPOINTS (Process Menu)
==================================
This displays any defined breakpoints: the breakpoint address,
and breakpoint type. Permanent breakpoints are denoted by '*' and conditional
by '?'. Count and stop breakpoints have a number displayed with represents
the remaining counter value (a stop breakpoint is a count breakpoint of value
1). Conditional breakpoints have their expressions displayed after the '?'.
By LMB on a breakpoint text line, the (upper) disassembly window can be moved
to the address of the breakpoint.
* ------------------------------------------------------------------------- *
15) Process Variables Memory
============================
As of V1.8, if a Process exists, it is possible to define an area
of memory as variables memory which is used by the Process. This memory may
be either within the Process's memory (project memory range), or it may have
been allocated by the Process. This is most useful when dissecting a program
which references its variables using either of the addressing modes ARID
(eg: '32(a4)'), or ARIDI (eg: '16(a5,d0.w)'), since it allows references
to known variables to be automatically replaced with user-defined symbols,
as will normally occur with direct address references to logged addresses.
The 'Process' menu contains an item 'Variables Memory'. This
will open a request window which contains: two string gadgets for input of
variables memory start and size; a single string gadget for input of the
address of a 'JSR _LVOAllocMem(a6)' instruction; and two more gadgets, 'Ax',
and 'Previous'.
The first two string gadgets allow the variables memory area to
be specified directly, if this is known. If you enter a start address and a
size which matches the address and size of any block of memory which is known
to have been allocated by the Process, then the address of the 'JSR AllocMem'
which allocated this memory will automatically be stored in the third string
gadget. It is also possible to enter the address of a 'JSR AllocMem', from
which Disect will be able to determine the address and size of the variables
memory. The 'Previous' gadget will automatically define all three string
gadgets according to the last memory allocation made by the Process. Note
that this is only possible if a memory monitor was installed when the Process
was created (see main preferences). The 'Ax' gadget allows you to select
which address register is to be taken as a variables memory base pointer.
The purpose of this is best illustrated by example. If you were
dissecting a Process which had allocated a block of memory and stored its
address in a4, or had done 'lea [1:0],a4', and you had the following:
move.b #24,32(a4)
If you LMB on the '32' and replace it with a user constant symbol which you
named 'some_var':
move.b #24,some_var(a4)
If the DEA is within a known variables memory area, then the
symbol 'some_var' is treated as a 'variable constant symbol'. What this means
is that whenever the PC reaches any instruction which contains either an ARID
or a ARIDI reference such as '32(a4)', then Disect will automatically replace
the '32' with the known variable symbol 'some_var'.
Since it is not necessarily true that all such references are
in fact references to variables memory, Disect will only automatically
replace these when the PC is at the relevant instruction (at which time it
is possible for Disect to know for certain). So, any references which are
found which might be variables are marked with a 'V' character next to where
breakpoint markers appear. If you wish to confirm that an instruction does
in fact reference variables memory, then you simply LMB on the 'V' marker.
Incidentally, whenever a DC.L is disassembled, if there is a program symbol
which exists which matches the value of the DC.L operand, then a 'P' marker
will be displayed, which can be LMB clicked in the same way to auto-replace.
All of the information contained in the Variables Memory request
window is saved as part of the DSCT data file, so that, for example, once
the 'JSR AllocMem' which allocates the variables memory has been identified,
Disect will automatically define the variables memory start and size when
this instruction is executed the next time you load the original Process (as
long as a memory monitor was installed when the Process was created).
* ------------------------------------------------------------------------- *
16) Grabbing An Existing Process
================================
The 'Project' menu item 'Grab Process' allows an existing memory-
resident Process to be grabbed, and used as if the Process had been created
by Disect in the normal way. A request window will open, which will list
all current Processes which are waiting, either as a result of a call to
Exec Wait(), or Exec WaitPort(). To grab a Process, simply LMB on its name
to select it, then click on the 'Grab' gadget. At this point, if the Process
is no longer Waiting, then Disect will not attempt to grab it. If the Process
is still Waiting, Disect will effectively send it one of the signal(s) it is
waiting for, and the Process will resume, under control of Disect. Lovely!
Also in the 'Project' menu is another item 'Ungrab Process'. This
will allow a grabbed Process to be resumed, no longer under the control of
Disect.
This feature should be used with caution. It is vital that some
Processes remain functional at all times, ie: it is not safe to grab them
since their activities must not be interrupted. The only way to discover if
a Process can be safely grabbed (and ungrabbed) is to try it. Note that some
Processes can be grabbed, and only when you attempt to ungrab them will
problems occur. You have been warned...
Another word of warning: a Process which has been grabbed may
have its SegList memory (the memory in which the Process resides) freed
automatically, as soon as the Process has replied to its WorkBench start-up
message. As a result, it may be unsafe to single-step the last instructions
of a Process, since the OS may free the Process's memory before the very last
instruction has been executed by Disect. As an example:
bsr close_down ; reply to WB message
moveq.l #0,d0 ; set return code
rts ; Process terminates here !
If you execute (key 'E') the bsr, the Process replies to its WB start-up
message, which may cause the Process's memory to be freed. Disect will
then have a PC at the moveq.l instruction, but any operation which uses
memory (eg: opening a Disect window) may cause the content of the PC
address to become corrupt. If this occurs, then you should select the
'Move PC To Return Code' item from the 'Process' menu. This will move
the PC to an address which is guaranteed to contain the final two
instructions in the example above.
* ------------------------------------------------------------------------- *
17) Auto Trace Mode
===================
Hopefully, this will at times prove to be a rather useful little
feature. What it does is to automatically trace the instructions of your
Process until some certain pre-specified condition is met. In conjunction
with Disect's automatic symbol replacement (ARID hardware register, Process
variables memory references, _LVOs), it can be quite revealing! Auto-trace
mode is accessed via the 'Process' menu, which will open a request window.
This contains a 'Resume' and a 'Quit' gadget: the first will enable auto
trace mode, whilst the second will not. Note that once enabled, auto trace
mode can be disabled by pressing the 'Esc' key. Whenever you save the main
program preferences, the current auto trace mode settings and expressions are
also saved. The remaining content of the auto trace request window is roughly
divided into two.
On the left, you have six check gadgets and two string gadgets.
These define the conditions which will cause auto trace mode to be disabled.
The first two check gadgets are used to define whether or not auto trace mode
is disabled whenever an instruction is reached which will attempt to perform
a word or long read/write using an odd source/destination effective address.
As with all the conditions which may disable auto trace mode, the Process
will 'suspend' before the current instruction has been executed.
The third check gadget is used to disable auto trace mode when-
ever the instruction at the PC is RTS. This can be used to effectively
resume the Process until the RTS of the current function/subroutine. Note
that Disect will count how many JSR/BSR instructions are traced, in order
to know how many RTS instructions must be ignored before the actual RTS
which will disable auto trace mode is reached.
The next check gadget, if checked, will cause auto trace mode
to be disabled whenever the destination effective address of an instruction
is not within 'permitted' memory. Disect considers the following to be
permitted:
1) The memory in which the Process resides.
2) The memory in which the Process's Process STRUCTURE resides.
3) The Process's stack.
4) Memory used by the LIB structure of any resident library.
5) Any memory allocated by the Process.
Any writes to memory allocated by the Process will only be detected as being
permitted if a memory monitor was installed when the Process was created (not
grabbed!). This option can be found in the Preferences request window. For
word or long writes to memory, Disect will also check if the address of the
last byte written is outside permitted memory.
The final two check gadgets are used to enable/disable each
expression entered into the two string gadgets. If enabled, before tracing
an instruction, Disect will evaluate an expression, and will disable auto
trace mode if the result is TRUE (non-zero). Note that this is the equivalent
of placing a conditional breakpoint at every instruction of your Process
(which would be otherwise impossible), including any external libraries or
functions, including ROM (also not otherwise possible). If the expression
contains either of the reserved symbol names 'SEA' and/or 'DEA', then if
an instruction does not have a source/destination effective address, the
expression will be ignored (for that instruction only). As a result, Disect
will not allow a single expression to contain BOTH 'SEA' and 'DEA' (since
this would result in the expression being ignored for instructions which
have only a source OR a destination effective address). This is why there
are two expressions permitted: one can contain 'SEA', and the other, 'DEA'.
The are other conditions which will always cause auto trace mode
to be disabled: if PC is 0 or odd; if the opcode at PC cannot be identified;
if the destination effective address is hardware register INTENA; if the
instruction at PC is privileged; or if a breakpoint is reached (if the
breakpoint would normally cause an active Process to be suspended).
In the right of the auto trace request window are seven check
gadgets used to control various options. The first two tell Disect whether
or not to trace ROM functions, and any external functions (not within the
memory range of the Process, and not in ROM). Whenever a JSR/BSR instruction
is reached, Disect uses the address of the subroutine to decide if it should
be traced. If not, then the JSR/BSR instruction is executed, as occurs via
pressing key 'E' normally, hence the subroutine will execute in real-time.
Note that a JSR/BSR is treated as a call to a ROM function either if the
subroutine address is in ROM, or if the instruction at this address is a JMP
into ROM (eg: exec.library). If a function is not traced, then auto trace
mode will resume after the function has returned.
In addition, if a JMP to a ROM/external function is reached,
(as will happen often with a Process written in 'C'), then Disect will check
the address on the top of the stack to see if it is within project memory
(it should be, since this is the rts address for the ROM/external function).
If not, Disect will disable auto-trace mode and display a message ('RTS out-
side project'). If this address is in project memory, then Disect will define
a stop breakpoint at this address, and the Process will be resumed at the JMP
instruction. When the function returns, the breakpoint will be reached, at
which point auto-trace mode will be enabled, as before.
The third check gadget will enable/disable writes to the history
buffer after each instruction has been traced. Whenever a JSR/BSR is executed
(ie: not traced), then the history buffer will be written to after the JSR/
BSR has completed, the function having returned successfully.
The final four check gadgets will enable/disable the refreshing
of the four main program windows after each instruction has been traced.
The second item in the Process menu is 'Resume Until RTS'. This
will enable auto-trace mode, with all options disabled except 'Suspend At
RTS'. This is useful for quickly getting to the end of the subroutine in
which the PC is currently located. Note that the 'Odd SEA' and 'Odd DEA'
options for auto trace mode will be as defined via the Auto Trace Mode
request window (ie: they are not automatically disabled during Resume Until
RTS).
Also in the 'Process' menu is another item 'Breakpoint After
External BSR/JSR'. If you're not interested in this then read no further...
Right, the reason I did this one was as follows: when tracing
ROM functions, more specifically exec.library Wait(), auto trace mode would
be disabled at the following instruction:
move.w #$4000,$dff09a ; disable interrupts
Now, we cannot possibly expect to continue auto-trace mode (take my word for
it...), so what this menu item will do is to place a stop breakpoint at the
address after the last traced internal JSR/BSR to an external function.
What this means is that somewhere within the memory range of our Process is
the following:
~ ~ ~
~ ~ ~
jsr _LVOWait(a6)
~ ~ ~
~ ~ ~
Since this is the (internal) JSR which called an external function, Disect
will define the breakpoint immediately after this instruction, and resume
the Process. Once the Wait() has completed, the Process will be suspended
after the JSR instruction. NOTE: before using this menu item, in this
example it is necessary to move the PC to the instruction before the
'move.w #,$dff09a' (ie: you MUST NOT use it with the PC at this instruction).
To move the PC to the previous instruction, you merely need to RMB on the
mnemonic of the instruction in the disassembly window. Remember this!
* ------------------------------------------------------------------------- *
18) Hardware Monitor
====================
If enabled, the hardware monitor allows an active Process to
alter the values of certain hardware registers, without crashing the system
when the Process is suspended. This also applies to a Process being active
in the sense of only executing a single instruction. At present, the status
of DMA flags, interrupt flags, and ADK flags are monitored, as well as most
system vectors. Support is not available for any Process which alters the
VBR. In addition, the Odd Address, Trace and Illegal vectors must not be
altered by the Process, since they are used by Disect.
The hardware monitor is enabled/disabled either using the first
item in the 'Hardware' menu, or by pressing the '/' (or '?') key.
The next three menu items will open request windows with which
the current Process DMA/INT/ADK flags can be seen, and altered using check
gadgets. The INT flags request window also contains a string gadget with
which you can alter the Process's interrupt level held in the status
register.
The next menu item allows access to a window which displays the
current Process vector addresses. These are automatically monitored whenever
your Process is resumed, and when it suspends. Note that it is NOT safe to
run a Process which alters the VBR. Also, the Odd Address, Trace, and Illegal
vector addresses must not be changed.
The next menu item opens a window which allows the required
blitter registers to be defined. Whenever an instruction which writes to
a blitter register is executed or traced, Disect will automatically store
the required value. This feature is used for Processes which, for example,
define BLTAMOD at the start, and then expect it to remain unchanged.
Following these are four menu items involved with defining the
required addresses for COP1LC and COP2LC when the Process is active. The two
check-items define which of COPJMP1 or COPJMP2 are to be strobed after the
required addresses have been written (either one of these, or neither). It
is not possible for Disect to automatically track the required addresses in
the same way as it is possible for DMA,etc flags, although if any instruction
is single-stepped which writes to COP1LC or COP2LC, then Disect will store
the required address. Similarly, any write to COPJMP1 or COPJMP2 will define
which of the two is to be used. This is not possible if a Process is resumed,
and the Process then writes to these registers while it is active.
The next menu item allows the defined copper list to be run.
This is useful with a Process which has a copper interrupt routine which,
for example, monitors the position of a mouse pointer. By running the copper
list, with copper DMA and interrupts enabled, and raster/sprite DMA, it is
then possible to move the pointer to a known position on the screen, and
press the LMB. To return to Disect, simply press both mouse buttons. Then,
you could trace your Process, which should respond to a mouse click over
a known screen position.
The next menu item ('Stack Top Address') allows you to define
the address above the stack whenever your Process directly alters a7, ie:
stack top address = highest stack address + 1. If you trace/execute a move
to a7, then this is defined automatically. Disect does not permit this if
the new stack memory is not part of your project. (In this case, you can
make it so by saving a MultiBin file). Once this address has been defined,
then Disect will not save the Process's stack when saving a Process's status
in a MultiBin file, since this memory should be part of the project. See also
the section about MultiBin files.
Disect also allows two user-definable functions to be used, one
to be called immediately before the Process is resumed (Pre-Execute), and
one to be called immediately before the Process is suspended (Post-Execute).
These functions are called by the Process itself (not by Disect). Each is
defined via its own request window, which contains a string gadget for input
of the function address, and a check gadget which is used to enable/disable
the function. A 'Load' gadget also allows an executable file to be loaded to
be used as a function.
Also in these request windows are 16 check gadgets which define
which registers must be preserved during the function, and 16 string gadgets
which allow register values to be passed to the function. If a register is
preserved, then it will be the same after the function as it was before the
function was called; any registers which are not preserved will contain the
return values from the function.
Any enabled function will be executed in Supervisor mode. The
function MUST remain in Supervisor mode, and MUST end with an 'RTS'.
As an example of the use of these functions, suppose you were
dissecting a Process which used the hardware to read a disk. The Process
will alter the system DMA/INT/ADK flags, which will prove to be no problem.
After single-stepping the code, you might reach the first disk read. The
Process can be resumed until after this, using a stop breakpoint. Suppose
that a little later, there is another disk read, at which point, under normal
execution, the drive motor will still be active, although under Disect, this
would not be so. In order to resume the Process until after this second disk
read, it is necessary to start the drive (otherwise, the Process will most
probably simply lock-up, with the hardware being in the state required by
the Process, not the OS). There are two alternatives: if the Process contains
a subroutine which only starts the drive, then this can be used as the Pre-
Execute function; or you could write a short bit of code to do this - perhaps
by disassembling a small part of the Process to a source file - and assemble
it as an executable file, which can be loaded to be used as the Pre-Execute
function.
The Pre-/Post-Execute functions could also be written to setup
any required hardware registers for the Process (Pre-), then restore them
for the OS (Post-). Hopefully, this will overcome any compatibility problems
which may occur...
A word of advice concerning blitter code. If you are debugging
some code which uses the blitter, then it is safe to execute such code as
long as you use the hardware monitor (assuming that the Process has already
'killed the system'/defined any required interrupt vectors - ie: as long as
no interrupts will occur which cause the OS to be called). By defining a stop
breakpoint after the instruction which writes to BLTSIZE, and resuming the
Process from the first instruction which writes a blitter address pointer,
the blit will begin with the hardware in the state required by the Process,
the breakpoint will be reached, Disect will wait for the blit to finish, and
then will restore the hardware for the OS.
There is one last thing I ought to mention, concerning count and
conditional breakpoints. Whenever the Process reaches either of these two
breakpoint types, then it will be suspended while Disect evaluates the break-
point in order to decide if the Process should be permanently suspended; if
not, then Disect will allow the Process to resume. The thing to note is that
when the Process is suspended (and possibly resumed), then any enabled Pre/
Post-Execute functions will be called. This will occur each time the break-
point is reached, until the Process is ultimately suspended.
* ------------------------------------------------------------------------- *
19) 68020 Modes/Instructions
============================
The following notes concern 68020-specific addressing modes, and
instructions:
1. In a 68020 effective address, only the base displacement can be replaced
by a symbol; the outer displacement cannot. For PC-relative modes, the value
displayed for the base displacement will be the result of adding it to the
PC value for the instruction. This address will be automatically replaced by
a matching program symbol (if the current preferences permit this). For modes
where the base register is an address register, if the base displacement is
a long, then an automatic program symbol match is checked for in the same
way.
2. The offset and width values for bit field instructions can be replaced by
symbols, although only a single user constant symbol is permitted. When using
the symbol selection window to replace a bit field offset/width value, the
symbol search type is pre-defined, and cannot be altered. Since these values
can be replaced by only one symbol each, the facility to enter an existing
symbol name (to be used as an offset) will be disabled.
If you replace a bit field value, the address of the BF instruction is not
logged in the usual way. This has no other implications, except it may save
you a little memory.
3. When a Process exists, during calculation of a 68020 effective address,
if any memory indirection attempts to read a non-existant address, then the
effective address will be considered invalid, and will not be displayed.
Also, if you're using a pre-68020 processor, any disassembly of 68020 modes
which attempts to perform a memory indirection at an odd address will render
the EA invalid, hence it will not be displayed.
4. The following 68020 instructions are not implemented: CAS, CAS2, CALLM,
RTM, PACK, UNPK.
* ------------------------------------------------------------------------- *
20) Installing To Hard Drive
============================
Ok, on the disk, the file 'DisectV1.8' is in fact a script. This
contains an ASSIGN:
ASSIGN DISECT: DisectV1.8:
The last name of this may be changed to reflect the partition
name where you wish to put Disect. Other than this, NOTHING else should be
altered. Simply copy the FOUR directories and FOUR files from the (floppy)
disk to (where-ever!). Important: DO NOT give the executable ('Disect.exe')
an icon in order to double-click on it to launch the program: ALWAYS double-
click on the script file ('DisectV1.8')
* ------------------------------------------------------------------------- *
21) Contact Address
===================
If you have any problems or suggestions concerning Disect, or
if you want the full version, here's the address to which you should send
a cheque or postal order for £30 (English!!).
Dave Alderson
86, Powell Ave
Marton
Blackpool
Lancashire
England
FY4 3HH
Last, but certainly by no means least, many, many, many thanks
to Bill Westhead for helping spread the (e-mail) word, and also to the
following people for helping to test out the early versions:
Marc Kelly
Mark Manning
Hark!
Is that the sound
of thirty pound
at the front door?
No! So,
perhaps we must
just
wait a little more ??? !!! ...
* ------------------------------------------------------------------------- *